# include "Renderer.h"

# include "Game.h"
# include "Module.h"
# include "GUI.h"
# include "AI.h"
# include "EventListener.h"

# include "Hero.h"

Renderer::Renderer( Game* game) : Module( game), myShutDown( false), myRoot( 0), myWindow( 0), mySceneManager( 0), myCamera( 0), myGUI( 0)
{

}

Renderer::~Renderer()
{

}

Ogre::RenderWindow* Renderer::getWindow()
{
	return myWindow;
}

Ogre::SceneManager* Renderer::getSceneManager()
{
	return mySceneManager;
}

bool Renderer::init( GUI* gui, AI* ai, EventListener* eventListener)
{
	myGUI = gui;
	myAI = ai;
	myEventListener = eventListener;
	
	myRoot = new Ogre::Root();

	setupResources();

	if( !setupConfig() )
	{
		return false;
	}

	Ogre::RenderSystem* rs = myRoot->getRenderSystemByName("OpenGL Rendering Subsystem");

	rs->setConfigOption("Full Screen", "No");
	rs->setConfigOption("VSync", "Yes");
	rs->setConfigOption("Video Mode", "800 x 600 @ 32-bit");
 
	myRoot->setRenderSystem(rs);

	myWindow = myRoot->initialise( true, "GameOfTheYear Render Window");

	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
	initSceneManager();
	initCamera();
	initViewport();

	myRoot->addFrameListener( this);
	initFrameListener();
	createScene();

	myAI->setWindow( myWindow);
	myEventListener->setWindow( myWindow);

	mySceneManager->setDisplaySceneNodes( true);

	return true;
}

void Renderer::start()
{
	myState = MENU_STATE;
	windowResized( myWindow);
	myRoot->startRendering();
}

Ogre::SceneNode* Renderer::createSceneNode( const Ogre::String& name)
{
	return mySceneManager->getRootSceneNode()->createChildSceneNode( name);
}

Ogre::Entity* Renderer::createEntity( const Ogre::String& name, const Ogre::String& mesh)
{
	return mySceneManager->createEntity( name, mesh);
}

Ogre::Camera* Renderer::createCamera( const Ogre::String& name)
{
	return mySceneManager->createCamera( name);
}

Ogre::Viewport* Renderer::createViewport( Ogre::Camera* camera)
{
	myWindow->removeAllViewports();
	return myWindow->addViewport( camera);
}

void Renderer::deleteEntity( Ogre::Entity* ent)
{
	mySceneManager->destroyEntity( ent);
}

void Renderer::deleteSceneNode( Ogre::SceneNode* sceneNode)
{
	mySceneManager->destroySceneNode( sceneNode);
}

void Renderer::deleteCamera( Ogre::Camera* camera)
{
	mySceneManager->destroyCamera( camera);
}

bool Renderer::frameRenderingQueued( const Ogre::FrameEvent& evt)
{
	if ( myWindow->isClosed() )
	{
		return false;
	}

	if ( myShutDown )
	{
		return false;
	}

	CEGUI::System::getSingleton().injectTimePulse( evt.timeSinceLastFrame);

	myGame->central( evt.timeSinceLastFrame);
	handleEvents();

	return true;
}

void Renderer::windowResized( Ogre::RenderWindow* renderWindow)
{
	unsigned int width, height, depth;
    int left, top;
    renderWindow->getMetrics( width, height, depth, left, top);

    const OIS::MouseState &ms = myEventListener->getMouse()->getMouseState();
    ms.width = width;
    ms.height = height;
}

void Renderer::handleEvents()
{
	while ( !myEvents.empty() )
	{
		Event evtTmp = myEvents.front();
		myEvents.pop();

		if ( evtTmp.message == NEW_GAME )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == QUIT )
		{
			myShutDown = true;
		}

		if ( evtTmp.message == CREATE_GAME_MENU )
		{
			myState = GUI_STATE;
		}

		if ( evtTmp.message == RETURN_GAME )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == OPEN_INVENTORY )
		{
			myState = GUI_STATE;
		}

		if ( evtTmp.message == CLOSE_INVENTORY )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == OPEN_COMPETENCE )
		{
			myState = GUI_STATE;
		}

		if ( evtTmp.message == CLOSE_COMPETENCE )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == RETURN_MENU )
		{
			myState = MENU_STATE;

			initCamera();
			initViewport();
		}

		if ( evtTmp.message == OPEN_TALK )
		{
			myState = GUI_STATE;
		}

		if ( evtTmp.message == CLOSE_GUI_WINDOW )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == CLOSE_TALK )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == OPEN_QUEST )
		{
			myState = GUI_STATE;
		}

		if ( evtTmp.message == CLOSE_QUEST )
		{
			myState = GAME_STATE;
		}

		if ( evtTmp.message == HERO_DEATH )
		{
			myState = GUI_STATE;
		}
	}
}

void Renderer::setupResources()
{
	Ogre::ConfigFile cFTmp;
	cFTmp.load( "resources.cfg");

	Ogre::ConfigFile::SectionIterator seciTmp = cFTmp.getSectionIterator();

	Ogre::String secNameTmp;
	Ogre::String typeNameTmp;
	Ogre::String archNameTmp;

	while ( seciTmp.hasMoreElements() )
	{
		secNameTmp = seciTmp.peekNextKey();
		Ogre::ConfigFile::SettingsMultiMap* settingsTmp = seciTmp.getNext();
		
		for ( Ogre::ConfigFile::SettingsMultiMap::iterator i = settingsTmp->begin(); i != settingsTmp->end(); i++ )
		{
			typeNameTmp = i->first;
			archNameTmp = i->second;
			Ogre::ResourceGroupManager::getSingleton().addResourceLocation( archNameTmp, typeNameTmp, secNameTmp);
		}
	}
}

bool Renderer::setupConfig()
{
	if ( !(myRoot->restoreConfig() || myRoot->showConfigDialog()) )
	{
		return false;
	}

	return true;
}

void Renderer::initSceneManager()
{
	mySceneManager = myRoot->createSceneManager( Ogre::ST_GENERIC);
}

void Renderer::initCamera()
{
	mySceneManager->destroyCamera( "Camera");
	myCamera = mySceneManager->createCamera( "Camera");

	myCamera->setPosition( 100.0f, 100.0f, 0.0f);
	myCamera->lookAt( 50.0f, 0.0f, 0.0f); 

	myCamera->setNearClipDistance( 5);
}

void Renderer::initViewport()
{
	myWindow->removeAllViewports();
	Ogre::Viewport* viewPortTmp = myWindow->addViewport( myCamera);
	viewPortTmp->setBackgroundColour( Ogre::ColourValue( 0.0f, 0.0f, 0.0f));
	myCamera->setAspectRatio( Ogre::Real( viewPortTmp->getActualWidth()) / Ogre::Real( viewPortTmp->getActualHeight()));
}

void Renderer::initFrameListener()
{
	Ogre::WindowEventUtilities::addWindowEventListener( myWindow, this);
}

void Renderer::createScene()
{
	
}